#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/of_irq.h> 
#include <linux/irq.h>
#include <linux/platform_device.h> 
#include <linux/miscdevice.h>
#include <linux/input.h>

#define KEYINPUT_CNT 	1 				/* 设备号个数 */ 
#define KEYINPUT_NAME 	"keyinput" 		/* 名字 */ 
#define KEYVALUE 		0X01 			/* KEY按键值 */ 
#define KEY_NUM 		2 				/* 按键数量 */

struct keyDesc_st
{
	unsigned char keycode;
	int preKeyValue;
	int gpio;
	int irqnum;
	unsigned char name[10];
	irqreturn_t (*handler)(int, void *);
};

struct inputbutton_st
{
	unsigned char currentKeyNum;
	struct device_node *node;
	struct timer_list timer;
	struct input_dev *inputdev;
	struct keyDesc_st key[KEY_NUM];
};
static struct inputbutton_st inputbutton;

static irqreturn_t inputbutton0_handler(int irqnum, void *ptr)
{
	inputbutton.currentKeyNum =0;
	mod_timer(&inputbutton.timer, jiffies+msecs_to_jiffies(10));

	return IRQ_RETVAL(IRQ_HANDLED);
}

static irqreturn_t inputbutton1_handler(int irqnum, void *ptr)
{
	inputbutton.currentKeyNum =1;
	mod_timer(&inputbutton.timer, jiffies+msecs_to_jiffies(10));

	return IRQ_RETVAL(IRQ_HANDLED);
}

static void timer_func(struct timer_list *ptr)
{
	int preValue,currentValue;
	int currentGpio = inputbutton.currentKeyNum;

	preValue = inputbutton.key[currentGpio].preKeyValue;
	currentValue = gpio_get_value(inputbutton.key[currentGpio].gpio);

	if(preValue ==1 && currentValue==0)
	{
		input_report_key(inputbutton.inputdev, inputbutton.key[currentGpio].keycode, 1);
		input_sync(inputbutton.inputdev);
	}
	else if(preValue ==0 && currentValue==1)
	{
		input_report_key(inputbutton.inputdev, inputbutton.key[currentGpio].keycode, 0);
		input_sync(inputbutton.inputdev);
	}

	inputbutton.key[currentGpio].preKeyValue = currentValue;
}

static int inputButton_init(struct platform_device *pdev)
{
	int i=0;
	int ret =0;

	inputbutton.node = pdev->dev.of_node;
	if(inputbutton.node ==NULL)
		goto node_err;

	for(i=0;i<KEY_NUM;i++)
	{
		inputbutton.key[i].gpio = of_get_named_gpio(inputbutton.node, "gpios", i);
		if(inputbutton.key[i].gpio <0)
		{
			printk("get gpio error\r\n");
			goto gpio_err;
		}
/*
		memset(inputbutton.key[i].name, 0,sizeof(inputbutton.key[i].name));
		sprintf(inputbutton.key[i].name,"key%d",i);
		ret = gpio_request(inputbutton.key[i].gpio, inputbutton.key[i].name);
		if(ret <0)
		{
			printk("gpio request error key:%d\r\n",i);
			goto gpio_err;
		}
*/
		ret = gpio_direction_input(inputbutton.key[i].gpio);
		if(ret <0)
		{
			printk("set gpio input error\r\n");
			goto gpio_err;
		}

		inputbutton.key[i].irqnum = irq_of_parse_and_map(inputbutton.node, i);
		if(inputbutton.key[i].irqnum <0)
			goto irq_err;

		inputbutton.key[0].handler = inputbutton0_handler;
		inputbutton.key[0].keycode = KEY_0;
		inputbutton.key[1].handler = inputbutton1_handler;
		inputbutton.key[1].keycode = KEY_1;
		inputbutton.key[i].preKeyValue = KEYVALUE;

		ret = request_irq(inputbutton.key[i].irqnum, inputbutton.key[i].handler, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, inputbutton.key[i].name, NULL);
		if(ret <0)
			goto irq_err;
	}
	
	return 0;
	
irq_err:
	for(i=0;i<KEY_NUM;i++)
	{
		gpio_free(inputbutton.key[i].gpio);
	}	
gpio_err:
node_err:
	return -EINVAL;
}

static int inputbutton_probe(struct platform_device *pdev)
{
	int ret = 0;
	int i=0;

	//提取node节点
	ret = inputButton_init(pdev);
	if(ret<0)
		goto node_err;

	//申请输入设备
	inputbutton.inputdev = input_allocate_device();
	if(IS_ERR(inputbutton.inputdev))
		goto inputDev_err;

	//设置事件
	__set_bit(EV_KEY, inputbutton.inputdev->evbit);
	__set_bit(EV_REP, inputbutton.inputdev->evbit);
	__set_bit(KEY_0, inputbutton.inputdev->keybit);
	__set_bit(KEY_1, inputbutton.inputdev->keybit);

	inputbutton.inputdev->name = KEYINPUT_NAME;

	//注册输入设备
	ret = input_register_device(inputbutton.inputdev);
	if(ret<0)
		goto inputDevRegister_err;

	//创建定时器
	timer_setup(&inputbutton.timer, timer_func,0);
	
	return 0;

inputDevRegister_err:
	input_free_device(inputbutton.inputdev);
inputDev_err:	
	for(i=0;i<KEY_NUM;i++)
	{
		free_irq(inputbutton.key[i].irqnum , NULL);
		gpio_free(inputbutton.key[i].gpio);
	}
node_err:
	return -EINVAL;
}

static int inputbutton_remove(struct platform_device *pdev)
{
	int i=0;

	for(i=0;i<KEY_NUM;i++)
	{
		free_irq(inputbutton.key[i].irqnum , NULL);
		gpio_free(inputbutton.key[i].gpio);
	}

	//删除定时器
	del_timer_sync(&inputbutton.timer);

	//卸载输入设备
	input_unregister_device(inputbutton.inputdev);
	input_free_device(inputbutton.inputdev);

	return 0;
}

static const struct of_device_id inputbutton_of_math[]=
{
	{.compatible = "my-keys"},
	{}
};

static struct platform_driver inputbutton_drv =
{
	.driver = 
	{
		.name 			= "inputbutton",
		.of_match_table = inputbutton_of_math,
	},
	.probe 	= inputbutton_probe,
	.remove	= inputbutton_remove,
};

static int __init inputbutton_init(void)
{
	return platform_driver_register(&inputbutton_drv);
}

static void __exit inputbutton_exit(void)
{
	platform_driver_unregister(&inputbutton_drv);
}

module_init(inputbutton_init);
module_exit(inputbutton_exit);
MODULE_AUTHOR("jtb");
MODULE_LICENSE("GPL");
